home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / fastlane.arc / TIMER.ASM < prev    next >
Assembly Source File  |  1985-10-20  |  14KB  |  312 lines

  1.           page     60, 120
  2.  
  3. ;----------------------------------------------------------------------------;
  4. ;  High Resolution Timer Test Program                                        ;
  5. ;                                                                            ;
  6. ;  Based on:  Smith, B and T Puckett  "Life in the Fast Lane", PC TECH       ;
  7. ;                 JOURNAL, vol. 1, no. 7, April 1984, pp. 62-74.             ;
  8. ;                                                                            ;
  9. ;  Modified by:  TA Fischer                                                  ;
  10. ;                                                                            ;
  11. ;  Modifications to code in article:                                         ;
  12. ;                                                                            ;
  13. ;     1) The calibration and code to be tested sections have been broken     ;
  14. ;        out into separate subroutines.  This means that no modification of  ;
  15. ;        this code is necessary to run timings.  Simply set up the two       ;
  16. ;        subroutines as noted below, assemble them separately, and link      ;
  17. ;        in this code.                                                       ;
  18. ;                                                                            ;
  19. ;     2) The number of clock ticks is printed out (albeit crudely), so       ;
  20. ;        one does not have to use debug to run this.                         ;
  21. ;                                                                            ;
  22. ;                                                                            ;
  23. ;     This is a control routine to be used in running high resolution        ;
  24. ;     timer tests.  The code to be tested should be placed in two            ;
  25. ;     subroutines:  "CALIB", containing any code whose effect is to be       ;
  26. ;     removed from the results (loop control, etc.), and "TEST", which       ;
  27. ;     should contain the actual code to be tested.  The subroutines          ;
  28. ;     should be assembled separately and linked with these routines.         ;
  29. ;     The following format should be used for the test routines:             ;
  30. ;                                                                            ;
  31. ;                                                                            ;
  32. ;     data     segment  public byte                                          ;
  33. ;              ; declare here any storage required by test routines          ;
  34. ;     data     ends                                                          ;
  35. ;                                                                            ;
  36. ;                                                                            ;
  37. ;     code     segment  public byte                                          ;
  38. ;              assume   cs: code                                             ;
  39. ;                                                                            ;
  40. ;              public   calib                                                ;
  41. ;     calib    proc     near                                                 ;
  42. ;              ; place the calibration code here                             ;
  43. ;              ret                                                           ;
  44. ;     calib    endp                                                          ;
  45. ;                                                                            ;
  46. ;              public   test                                                 ;
  47. ;     test     proc     near                                                 ;
  48. ;              ; place the test code here                                    ;
  49. ;              ret                                                           ;
  50. ;     test     endp                                                          ;
  51. ;                                                                            ;
  52. ;     code     ends                                                          ;
  53. ;              end                                                           ;
  54. ;                                                                            ;
  55. ; The routine prints out the number of 0.84 microsecond clock ticks (in hex) ;
  56. ;----------------------------------------------------------------------------;
  57.  
  58.           page
  59. stack     segment  stack para
  60.  
  61.           db       32 dup ('stack   ')
  62.  
  63. stack     ends
  64.  
  65.  
  66. data           segment  public byte
  67.  
  68. a_cal_high     dw       ?          ; first timer readings
  69. a_cal_low      dw       ?          ;
  70. a_cal_ext      dw       ?          ;
  71. b_cal_high     dw       ?          ; second timer readings
  72. b_cal_low      dw       ?          ;
  73. b_cal_ext      dw       ?          ;
  74.  
  75. hextable       db       '0123456789ABCDEF'
  76. outstr         db       '000000000000$'
  77.  
  78. data           ends
  79.  
  80.  
  81. bios_data_seg  equ      40h
  82. bios_data      segment  at 40h
  83.                org      6Ch
  84. timer_low      dw       ?
  85. timer_high     dw       ?
  86. bios_data      ends
  87.  
  88.  
  89. code      segment  public byte
  90.           assume   cs: code
  91.  
  92. timer_0   equ      40h             ; 8293 counter port 0
  93. timer_ctl equ      43h             ; 8253 control port
  94. timer_lat equ      00h             ; 8253 command to save ch. 0 current count
  95. timer_set equ      00110100b       ; 8253 counter 0, mode 2, binary
  96.  
  97.  
  98.           page
  99.  
  100. ;----------------------------------------------------------------------------;
  101. ;  Program TIMERT03 -- High Resolution Timer Test Skeleton                   ;
  102. ;                                                                            ;
  103. ;     This is a skeleton of a control routine to be used in running          ;
  104. ;     high resolution timer tests.  The code to be tested is included        ;
  105. ;     in this module or called from it.  This routine calls subroutines      ;
  106. ;     TIMERR01 and TIMERS02 for setting and reading Counter 0 of the 8253.   ;
  107. ;     It is normally run under DEBUG to allow a breakpoint to be set to      ;
  108. ;     examine the results of the timing test.                                ;
  109. ;----------------------------------------------------------------------------;
  110.           extrn    calib: near    ; calibration routine
  111.           extrn    test: near     ; test routine
  112.  
  113.           public   TIMERT03
  114. TIMERT03  proc     far
  115.  
  116.           push     ds              ; make return linkage
  117.           xor      ax, ax
  118.           push     ax
  119.           mov      ax, data        ; get data segment addressable
  120.           mov      ds, ax
  121.           assume   ds: data
  122.  
  123. tester:   call     timers01        ; get 8253 counter 0 running in Mode 2
  124.           call     timerr02        ; begin calibration pass
  125.           call     timerr02        ;   seem to need an extra one here
  126.           mov      a_cal_ext, cx
  127.           mov      a_cal_low, bx
  128.           mov      a_cal_high, ax  ; initial extended timer count now saved
  129.  
  130.           ;------------------------------------------------------------------;
  131.           ;  Beginning of calibration pass                                   ;
  132.           ;------------------------------------------------------------------;
  133.  
  134.           ;  Put here any test code whose effect is to be removed from the
  135.           ;    results, such as loop control statements ...
  136.           call     calib           ; Call routine containing calibration code
  137.  
  138.           ;------------------------------------------------------------------;
  139.           ;  End of calibration pass                                         ;
  140.           ;------------------------------------------------------------------;
  141.  
  142.           call     timerr02        ; end of calibration pass, begin test pass
  143.           mov      b_cal_ext, cx
  144.           mov      b_cal_low, bx
  145.           mov      b_cal_high, ax
  146.  
  147.           ;------------------------------------------------------------------;
  148.           ;  Beginning of test pass                                          ;
  149.           ;------------------------------------------------------------------;
  150.  
  151.           ;  Put test code here ...
  152.           call     test            ; Call routine containing test code
  153.  
  154.           ;------------------------------------------------------------------;
  155.           ;  End of test pass                                                ;
  156.           ;------------------------------------------------------------------;
  157.  
  158.           call     timerr02        ; end of test pass
  159.           add      cx, a_cal_ext   ; calculate (C-B)-(B-A) as ((C+A)-B)-B
  160.           adc      bx, a_cal_low   ; ADC to allow for carry in preceding ADD
  161.           adc      ax, a_cal_high  ; now have C+A
  162.  
  163.           sub      cx, b_cal_ext   ; Compute (C+A)-B
  164.           sbb      bx, b_cal_low
  165.           sbb      ax, b_cal_high
  166.  
  167.           sub      cx, b_cal_ext   ; Compute ((C+A)-B)-B in timer counts
  168.           sbb      bx, b_cal_low   ; as a 6 byte field in AX, BX, and CX
  169.           sbb      ax, b_cal_high
  170.  
  171. halt:     push     ax
  172.           mov      ax, ds
  173.           mov      es, ax
  174.           mov      di, offset outstr
  175.           pop      ax
  176.           call     regtohex
  177.           mov      ax, bx
  178.           call     regtohex
  179.           mov      ax, cx
  180.           call     regtohex
  181.  
  182.           mov      dx, offset outstr
  183.           mov      ah, 9
  184.           int      21h
  185.  
  186.           ret
  187.  
  188. TIMERT03  endp
  189.  
  190.  
  191.           page
  192.  
  193. ;----------------------------------------------------------------------------;
  194. ;  Public Procedure TIMERS01 -- High Resolution Timer Setup                  ;
  195. ;                                                                            ;
  196. ;     This is a subroutine to set up Counter 0 of the 8253 to run in Mode 2. ;
  197. ;     It normally runs in Mode 3, which makes its residual count values      ;
  198. ;     useless for high resolution timing purposes since in this mode it      ;
  199. ;     counts down by twos, with two countdowns per cycle.  In Mode 2, there  ;
  200. ;     is a single countdown per cycle, by ones, so the residual count values ;
  201. ;     are meaningful.  (See routine TIMERR02 for recovering timing           ;
  202. ;     information.)                                                          ;
  203. ;----------------------------------------------------------------------------;
  204.           public   TIMERS01
  205. TIMERS01  proc     near
  206.  
  207.           push     ax              ; preserve
  208.           push     cx
  209.  
  210.           mov      al, timer_set   ; set Counter 0 parameters, prime
  211.           out      timer_ctl, al   ;   load trigger
  212.           xor      al, al          ; zero will give full count of 65536
  213.           nop                      ; insure 5 clocks for 8253 recovery time
  214.           out      timer_0, al     ; load low order byte
  215.           nop                      ; 8253 recovery time
  216.           nop                      ;  "       "      "
  217.           out      timer_0, al     ; load high order byte
  218.           mov      cx, 20000       ; must be sure previous countdown done
  219. loop:     loop     loop            ; so spin here 70 ms to guarantee it
  220.  
  221.           pop      cx              ; restore
  222.           pop      ax
  223.           ret
  224.  
  225. TIMERS01  endp
  226.  
  227.  
  228.           page
  229.  
  230. ;----------------------------------------------------------------------------;
  231. ;  Public Procedure TIMERR02 -- High Resolution Timer Read Routine           ;
  232. ;                                                                            ;
  233. ;     This is a subroutine to return high resolution timing information      ;
  234. ;     obtained from the BIOS TIMER_LOW and TIMER_HIGH fields, extended       ;
  235. ;     with low order information obtained from the current residual count    ;
  236. ;     of Counter 0 of the 8253.  (See routine TIMERS01 for initializing      ;
  237. ;     Counter 0.)                                                            ;
  238. ;----------------------------------------------------------------------------;
  239.           public   TIMERR02
  240. TIMERR02  proc     near
  241.  
  242.           push     ds             ; get pointer to BIOS data area
  243.           mov      ax, bios_data_seg
  244.           mov      ds, ax
  245.           assume   ds: bios_data
  246.  
  247.           mov      al, timer_lat   ; timer 0, latch
  248.  
  249.           cli                      ; hold off interrupts while fetching data
  250.           out      timer_ctl, al   ; latch current count in 8253
  251.           mov      bx, timer_low   ; get matching values
  252.           mov      cx, timer_high  ;
  253.           in       al, timer_0     ; read in low order byte
  254.           mov      ah, al          ; tuck it out of the way
  255.           nop                      ; insure 5 clocks for 8253 recovery
  256.           in       al, timer_0     ; read in high order byte
  257.           sti                      ; allow interrupts again
  258.  
  259.           xchg     ah, al          ; get in right order in register
  260.           neg      ax              ; get up count from down
  261.           xchg     ax, cx          ; return in common register orter
  262.           pop      ds
  263.           ret
  264.  
  265. TIMERR02  endp
  266.  
  267.  
  268.           page
  269.  
  270.           ; Convert register AX to a hex string located at ES:DI
  271.           public   regtohex
  272. regtohex  proc     near
  273.           assume   ds: data
  274.  
  275.           push     bx
  276.           push     cx
  277.           push     dx
  278.  
  279.           cld
  280.           mov      cl, 4
  281.           mov      dx, ax
  282.           mov      bx, offset hextable
  283.  
  284.           shr      ax, cl
  285.           and      ax, 0F0Fh           ; mask for first and third nibble
  286.           and      dx, 0F0Fh           ; mask for second and fourth nibble
  287.  
  288.           xchg     ah, al              ; upper nibble
  289.           xlat
  290.           stosb
  291.  
  292.           mov      al, dh              ; second nibble
  293.           xlat
  294.           stosb
  295.  
  296.           mov      al, ah               ; third nibble
  297.           xlat
  298.           stosb
  299.  
  300.           mov      al, dl               ; lower nibble
  301.           xlat
  302.           stosb
  303.  
  304.           pop      dx
  305.           pop      cx
  306.           pop      bx
  307.           ret
  308.  
  309. regtohex  endp
  310.  
  311. code      ends
  312.           end      TIMERT03